home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 130_01 / disku.c < prev    next >
Text File  |  1985-03-09  |  17KB  |  620 lines

  1. /*
  2.     DISK UTILITY PROGRAM
  3.  
  4.     Written by Richard Damon
  5.     Version 1.0 May 1980
  6.  
  7.     Revised by Bob Pasky
  8.     Version 2.0 July 1981
  9.     Version 2.4 Oct. 1981
  10.  
  11.     This program allows the operator to examine and modify
  12. a CPM diskette, either single density or Micromation's version of
  13. double density.
  14.  
  15.     The commands available in this package are :
  16.  
  17. Tn  set current track to n (0-76)
  18. Sn  set current sector to n (1-26/52)
  19. Ln  set current logical sector to n (0-25/51)
  20. Dn  set current disk number to n (0-3)
  21. Bn  set current track and sector to point to block n (0-F2)
  22. N   set current track and sector to next sector/block
  23.     next sector if last set command was for track or sector
  24.     next block if last set command was for block
  25. I   increment sector, if sector>max set to 1 and increment track
  26. R   read sector/block into buffer
  27. W   write sector/block from buffer
  28. P   print out contents of buffer, along with track/sector/block information
  29. Ea n n n n
  30.     edit buffer starting from location a filling with values n n n
  31. Aa "ccc..."
  32.     edit buffer starting from location a with ascii characters ccc...
  33. Fn  fill buffer with value n
  34. X   exit program
  35. M   print disk allocation map
  36. Cn  collate directory: n=0 orders by file type (from typtbl), n=1 by name
  37. ?   prints current track, sector, block info
  38. /   repeats last command string
  39.  
  40. Notes:
  41.     1)  Multiple commands may be specified on a line except for X and /
  42. which must be the only command on the line followed by return.
  43.     2)  Commands may be in upper or lower case letters
  44.     3)  Spaces are ignored except in the E command where they are used
  45.     as separaters for the numbers
  46.  
  47. Typical commands:
  48. d0t0s1rp    read in the track 0 sector 1 of disk 0 (Drive A) and print it
  49. e1A 4F 20 11    set buffer location 1A to 4F, 1B to 20, and 1C to 11.
  50. e0a 00w        set buffer location 0a to 0 and write buffer
  51.             Note no space after last data byte
  52. nrp        get next buffer and print it
  53.  
  54. Disk Allocation Map
  55.     The M command is designed to allow the directory blocks (blocks 0 and 1)
  56. to be printed out in a convient format. The directory is print out in the
  57. following format:
  58.  
  59.  Section 1:
  60.     The top half of the directory listing is a listing of the name
  61.     inforamtion of the directory entries.  Each line corresponds to 1 sector
  62.     of the directory.  A typical entry would be f=DISKTESTCOM/1 4c
  63.     The first letter is a code letter used to referance into section 2.
  64.     The equal sign indicats that the file exists, a star here indicates
  65.        that this entry is a deleted file.
  66.     Next comes the filename and extension.
  67.     The following /n is printed if this is other then the first extent 
  68.        (extent 0) of a file where n is the extent number of this entry.
  69.     The following number is the hex record count for this extent.
  70.  
  71.  Section 2:
  72.     The bottom half of the directory listing is a disk allocation map
  73.     showing which blocks are in use and by which file. Free blocks are
  74.     indicated by a dot while used blocks are marked by the file control
  75.     letter asigned to a file in section 1.  This listing has been blocked off
  76.     in groups of 8 and 16 to ease reading.
  77.  
  78. DIRECTORY SORTING
  79.  
  80.     Collating (sorting) the directory only places the sorted directory
  81. in the buffer. From there you can Write it back to the disk if desired,
  82. producing a sorted directory on the disk. The track, sector and block size
  83. are set up by Collate to their proper values for writing to the directory.
  84.  
  85.     Sorting can be performed alphabetically by the full name, type and
  86. extent, or grouped by type using a table within this program to sort by
  87. type -- within each type the files are ordered by name and extent. File
  88. types not found in the table are placed at the end, arranged by name, type
  89. and extent.
  90.  
  91. CPM FILE STRUCTURE
  92.  
  93.     To help the user of this program the following is a brief description
  94. of the format used in CPM. (Double density values are shown in parentheses.)
  95. The first 2 tracks of a disk are reserved for the bootstrap and the copy of
  96. the CPM operating system.  Tracks 2 through 76 store the data.  To speed up
  97. disk access CPM does not store consecutive data in consecutive sectors.
  98. Instead it uses every (8th or) 6th sector for data. Thus to read logical
  99. consecutive sectors you must read the sectors in the following order:
  100.  
  101. (single density only)
  102.  1 7 13 19 25 5 11 17 23 3 9 15 21 2 8 14 20 26 6 12 18 24 4 10 16 22
  103.  
  104. This interleaving is taken care of when reading in multiple sectors
  105. or when incrementing the disk address with the N command.  To simplify
  106. the disk allocation scheme the sectors are the collected into groups of
  107. (16 or) 8 sectors forming a (2k or) 1k block.  These blocks are numbered
  108. from 0 starting with the beginning of the directory -- track 2 sector 1.
  109. Block numbers range from 0 to F2 (hex).
  110.     The directory is organized to use (1 or) 2 blocks of storage -- 16
  111. sectors -- to store information on 64 file extensions.  A file extension
  112. is a part of a file up to 16k bytes long.  The directory entry for a file 
  113. extension is as follows:
  114.  
  115. byte  0   : file code : 0 if file exists, E5 if file is deleted
  116. byte  1- 8: file name : ascii representation of file name
  117. byte  9-11: file type : ascii representation of file type
  118. byte 12   : file ext  : binary number for extent number (0 to ?)
  119. byte 13,14: unused
  120. byte 15   : rec count : count of number of sectors in extent
  121. byte 16-31: map       : list of block numbers used by this extent
  122.  
  123. */
  124.  
  125. #include <bdscio.h>
  126.  
  127. #define MAXTYP    14    /* how many file types to sort on */
  128. #define SORTED    '~'    /* this may need changing for CP/M 2.x;
  129.                anything not seen in file_code is ok */
  130. #define DELETED    0xe5    /* ...anything except E5, of course */
  131. #define ESCAPE 0x1b
  132. #define STRDLM '"'
  133.  
  134. int    DEBUG;
  135. int    maxsecs, blocksecs, interval, typ, presdisk;
  136. char    density, buffer[2048], dir[2048], map[256];
  137. STATIC_char *typtbl[MAXTYP];
  138.  
  139. main(ac,av)
  140. int ac;
  141. char **av;
  142. {
  143.     int track, sector, disk, nsect, s, t, rs, rt, i, j, k, block;
  144.     char buff[80], prevbuff[80], *bufp, c, d, mc;
  145.  
  146.     disk=0;
  147.     track=rt=rs=0;
  148.     sector=1;
  149.     nsect=1;
  150.  
  151.     DEBUG = 0;
  152.     if (ac > 1 && (*av[1] == 'D')) DEBUG = 1;
  153. if(DEBUG)printf("\nDebug on...\n");
  154.  
  155.     presdisk = bdos(25,0);    /* find out which disk called from */
  156.  
  157.     typtbl[0]="COM";    /* change this table as desired */
  158.     typtbl[1]="SUB";
  159.     typtbl[2]="CRL";
  160.     typtbl[3]="CCC";
  161.     typtbl[4]="H  ";
  162.     typtbl[5]="C  ";
  163.     typtbl[6]="   ";
  164.     typtbl[7]="HEX";
  165.     typtbl[8]="DOC";
  166.     typtbl[9]="TXT";
  167.     typtbl[10]="BAK";
  168.     typtbl[11]="BRL";
  169.     typtbl[12]="TMP";
  170.     typtbl[13]="BAD";    /* note that the typtbl vector contains
  171.                    only pointers to the strings
  172.                         ********/
  173.  
  174.     printf("\n\t\tDisk Utility v 2.4\n");
  175.  
  176.     printf("Density on %c is Double\n", presdisk+65);
  177.     maxsecs = 52;
  178.     blocksecs = 16;
  179.     interval = 8;
  180.  
  181.     prevbuff[0] = '\0';    /* init last command string to nil */
  182.  
  183.     printf("Command? ");
  184.     while(tolower(*(bufp=gets(buff))) != 'x' || *(bufp+1) != '\0'){
  185.         if((*bufp == '/') && (*(bufp+1) == '\0'))
  186.             strcpy(buff,prevbuff);
  187.  
  188.         strcpy(prevbuff,buff);    /* save last command string */
  189.  
  190.         while((c=*bufp++) != '\0')
  191.         switch(toupper(c)){
  192.             case 'T' : track=getnum(&bufp,0,76,10,'T',track);
  193.                 nsect=1;
  194.                 break;
  195.  
  196.             case 'S' : sector=getnum(&bufp,1,maxsecs,10,'S',
  197.                             sector);
  198.                 nsect=1;
  199.                 break;
  200.  
  201.             case 'L' : s=getnum(&bufp,0,maxsecs-1,10,'L',
  202.                             tolog(sector));
  203.                 sector = tophys(s);
  204.                 nsect=1;
  205.                 break;
  206.  
  207.             case 'D' : disk=getnum(&bufp,0,3,10,'D',presdisk);
  208.                 do {
  209.                 printf("\nDensity of %c? (s/d) ", disk+65);
  210.                 density = tolower(getchar());
  211.                 } while (density != 's' && density != 'd');
  212.                 if (density == 's') {
  213.                     printf("ingle\n");
  214.                     maxsecs = 26;
  215.                     blocksecs = 8;
  216.                     interval = 6;
  217.                     }
  218.                 else    {
  219.                     printf("ouble\n");
  220.                     maxsecs = 52;
  221.                     blocksecs = 16;
  222.                     interval = 8;
  223.                     }
  224.                 break;
  225.  
  226.             case 'B' : block=getnum(&bufp,0,0xf2,16,'B',block);
  227.                 nsect=blocksecs;
  228.                 track=2 + block*blocksecs / maxsecs;
  229.                 s = block*blocksecs % maxsecs;
  230.                 sector = tophys(s);
  231.                 break;
  232.  
  233.             case 'N' : for(i=0;i<nsect;i++){
  234.                     sector = bumpsector(sector);